import { isObject, isUndefined } from 'lodash';

import { CONNECT_WEBSOCKET, RECONNECT_WEBSOCKET,
    WEBSOCKET_CONNECTED, WEBSOCKET_CONNECTING, 
    WEBSOCKET_DISCONNECTED, WEBSOCKET_ERROR } from '../reducers/websocket-conn.js';

const WEBSOCKET_SERVER_PORT = process.env.WS_PORT;

/**
 * Get url for websocket connection
 * @return {string}
 */
function getWebSocketPath() {
    if (process.env.BROWSER) {
        return `ws://${window.location.hostname}:${WEBSOCKET_SERVER_PORT}/`;
    } else {
        return `ws://localhost:${WEBSOCKET_SERVER_PORT}/`;
    }
}

/**
 * Create middleware for websocket
 * @return {Function}
 */
export default function websocketMiddleware({
    autoReconnect = true,
    reconnectInterval = 1000
} = {}) {
    const url = getWebSocketPath();
    let socket = null;

    return store => {
        const onOpen = (evt) => {
            store.dispatch({
                type: WEBSOCKET_CONNECTED
            });
        };

        const onClose = (evt) => {
            store.dispatch({
                type: WEBSOCKET_DISCONNECTED
            });

            // Try to reconnect
            if (autoReconnect) {
                setTimeout(() => {
                    store.dispatch({
                        type: RECONNECT_WEBSOCKET
                    });
                }, reconnectInterval);
            }
        };

        const onMessage = (evt) => {
            try {
                const action = JSON.parse(evt.data);

                store.dispatch(action);
            } catch (e) {
                onError({
                    data: `Failed to parse message: ${evt.data}`
                });
            };
        };

        const onError = (evt) => {
            store.dispatch({
                type: WEBSOCKET_ERROR,
                payload: {
                    err: evt.data
                }
            });
        };

        return next => action => {
            // 连接 WebSocket 服务
            if (action.type === CONNECT_WEBSOCKET ||
                action.type === RECONNECT_WEBSOCKET) {
                //Start a new connection
                if (socket != null) {
                    socket.close();
                }

                socket = new WebSocket(url);

                store.dispatch({
                    type: WEBSOCKET_CONNECTING
                });

                socket.onmessage = onMessage;
                socket.onclose = onClose;
                socket.onopen = onOpen;
                socket.onerror = onError;
            }

            // 发送信息
            if (action.via === 'ws') {
                socket.send(JSON.stringify({
                    type: action.type,
                    payload: action.payload
                }));
            }

            return next(action);
        };
    };
}